home *** CD-ROM | disk | FTP | other *** search
- /*
- * The game of Qix for the Sun3 workstation running Sunview (probably 3.0)--
- * Appearance ONLY shamelessly stolen from the real video game wonderfully
- * and admirably written by individual(s) unknown at Taito Corp (I think).
- *
- * Copyright 1987 by Dan Heller (island!argv@sun.com or argv@spam.istc.sri.com)
- *
- * Various polygon filling routines written by
- * -- Dan "Sky" Shultz (island!sky@sun.com) and
- * -- Don Hatch (splat%ucscb@ucscc.ucsc.edu [fall, 1987])
- * additional help (general debugging, recursive polyfill)
- *
- * Move mouse to go in direction. Left button does fast draw. Middle does
- * slow draw. Rogue/vi keys moves -- upper case draws. There is no slow
- * draw for keyboard input.
- *
- * There is not yet a stage where you split two qix.
- *
- * Sparx don't do what they should; they move randomly and without purpose.
- * They only kill the user -- there are no aggressive sparx.
- *
- * The qix will sometimes get into an infinite loop trying to get itself
- * or a portion of itself out of a place it shouldn't be (closed area).
- */
-
- #include "qix.h"
-
- /* the main icon for when the tool is closed */
- short qix_icon_dat[] = {
- #include "qix.icon"
- };
- DEFINE_ICON_FROM_IMAGE(qix_icon, qix_icon_dat);
-
- int (*old_repaint_func)();
-
-
- redraw(args)
- {
- stop_timer();
- (*old_repaint_func)(&args);
- start_timer();
- }
-
- main(argc, argv)
- char *argv[];
- {
- int catch();
- char **newargv = argv;
-
- (void) signal(SIGBUS, catch);
- (void) signal(SIGSEGV, catch);
- (void) signal(SIGXCPU, catch);
-
- #ifdef DEBUG
- /*
- * specify debug levels "-d level"
- * a level of 2 prints polygon fill info. 4 disables spark-generation
- * but doesn't kill current sparks. debug level 1 does prints things...
- */
- while (*++newargv)
- if (!strcmp(*newargv, "-q"))
- no_qix_kill = 1;
- else if (!strcmp(*newargv, "-d"))
- debug = (*++newargv) ? atoi(*newargv) : 1;
- #endif DEBUG
-
- frame = window_create(NULL, FRAME,
- FRAME_LABEL, argv[0],
- WIN_X, 250, WIN_Y, 45,
- FRAME_ICON, &qix_icon,
- FRAME_ARGS, argc, argv,
- FRAME_NO_CONFIRM, TRUE,
- 0);
-
- Draw = window_create(frame, CANVAS,
- WIN_HEIGHT, BOARD_HEIGHT_IN_PIXELS,
- WIN_WIDTH, BOARD_WIDTH_IN_PIXELS,
- WIN_EVENT_PROC, move_joystick,
- 0);
-
- draw_win = canvas_pixwin(Draw);
- window_set(Draw,
- CANVAS_FAST_MONO, TRUE,
- WIN_CONSUME_PICK_EVENTS,
- WIN_MOUSE_BUTTONS,
- 0,
- WIN_CONSUME_KBD_EVENTS,
- WIN_ASCII_EVENTS,
- SHIFT_CTRL, SHIFT_META,
- 0,
- WIN_INPUT_DESIGNEE, window_get(Draw, WIN_DEVICE_NUMBER),
- 0);
-
- Joystick = window_create(frame, CANVAS,
- WIN_X, 0,
- WIN_BELOW, Draw,
- WIN_HEIGHT, 68,
- WIN_WIDTH, WIN_EXTEND_TO_EDGE,
- 0);
- joystick_win = canvas_pixwin(Joystick);
-
- window_fit(frame);
-
- if (!(small_font = pf_open("/usr/people/argv/computer.14")) &&
- !(small_font = pf_default()) ||
- !(big_font = pf_open("/usr/lib/fonts/fixedwidthfonts/serif.r.16")) &&
- !(big_font = pf_default()))
- perror("can't open default font"), exit(1);
-
- level = -2; /* two screens before player may split two qix */
- moving = NO_MOVE;
- fast = 1,
-
- srandom(time(0));
- srand(time(0));
- update_score();
-
- init_qix();
- draw_joystick();
- pw_text(joystick_win, 92, 24, PIX_SRC, small_font, "Fast Slow");
- play_mode = SHOW_SCORES;
- update_score();
- score_board(TRUE, FALSE);
- time_left = 100; /* timeout before next demo mode switch */
- (void) signal(SIGALRM, move_pen);
- old_repaint_func = (int(*)())window_get(frame, CANVAS_REPAINT_PROC);
- window_set(frame, CANVAS_REPAINT_PROC, redraw, 0);
- start_timer();
-
- window_main_loop(frame); /* main loop to read input */
- exit(0);
- }
-
- clear_board()
- {
- register int x, y;
-
- clear_sparks();
- area_closed = 0;
-
- pen_x = (BOARD_WIDTH-1)/2, pen_y = BOARD_HEIGHT-1;
- remove_msgs(1);
-
- /* give left->right sweeping effect like the real game */
- for (x = 0; x < BOARD_WIDTH_IN_PIXELS; x++)
- draw(x, 0, x, BOARD_HEIGHT_IN_PIXELS-1, PIX_CLR);
-
- box(convert_x(0), convert_y(0),
- convert_x(BOARD_WIDTH-1), convert_y(BOARD_HEIGHT-1), PIX_SRC);
-
- /* clear the interior of the board */
- for (x = 1; x < BOARD_WIDTH-1; x++)
- for (y = 1; y < BOARD_HEIGHT-1; y++)
- board[x][y] = 0;
-
- for (x = 1; x < BOARD_WIDTH-1; x++) {
- board[x][0] = CL_LN_LF | CL_LN_RT | OLD_LINE | CL_PNT_TOP;
- board[x][BOARD_HEIGHT-1] = CL_LN_LF | CL_LN_RT | OLD_LINE | CL_PNT_BOT;
- }
-
- for (y = 1; y < BOARD_HEIGHT-1; y++) {
- board[0][y] = CL_LN_UP | CL_LN_DN | OLD_LINE | CL_PNT_LEFT;
- board[BOARD_WIDTH-1][y] = CL_LN_UP | CL_LN_DN | OLD_LINE | CL_PNT_RIGHT;
- }
- /* set the corners explicitly */
- board[0][0] = (CL_LN_DN | CL_LN_RT | CL_PNT_TOP | CL_PNT_LEFT | OLD_LINE);
- board[0][BOARD_HEIGHT-1] =
- (CL_LN_UP | CL_LN_RT | CL_PNT_BOT | CL_PNT_LEFT | OLD_LINE);
- board[BOARD_WIDTH-1][0] =
- (CL_LN_DN | CL_LN_LF | CL_PNT_TOP | CL_PNT_RIGHT | OLD_LINE);
- board[BOARD_WIDTH-1][BOARD_HEIGHT-1] =
- (CL_LN_UP | CL_LN_LF | CL_PNT_BOT | CL_PNT_RIGHT | OLD_LINE);
- }
-
- /*
- * change the status of the player. If he's living, we add special
- * effects and do the cleanup from the last game. setup the right icons
- * and grab all the io on the screen. If he's dead, release the IO
- * from the screen and reset critical values.
- */
- change_life(live_or_die)
- {
- register int x, n, m = (live_or_die == -1)? 40 : 300;
-
- stop_timer();
- if (live_or_die == LIVE) {
- move_fuse(fuse = (struct region *)NULL); /* erase the last fuse */
- if (region) {
- pen_x = region->x, pen_y = region->y;
- rm_cur_line(PIX_CLR); /* remove the current line drawn */
- }
- if (lives <= 0) {
- if (play_mode == DEMO)
- lives = 1;
- else
- lives = MAX_LIVES;
- clear_board(); /* resets pen_x, pen_y */
- level = -2, score = 0;
- } else {
- extern int qix1_x0[], qix1_x1[], qix1_y0[], qix1_y1[];
- extern int qix2_x0[], qix2_x1[], qix2_y0[], qix2_y1[];
-
- draw(convert_x(qix1_x0[0]), convert_y(qix1_y0[0]),
- convert_x(qix1_x1[0]), convert_y(qix1_y1[0]), PIX_CLR);
- if (level >= 0)
- draw(convert_x(qix2_x0[0]), convert_y(qix2_y0[0]),
- convert_x(qix2_x1[0]), convert_y(qix2_y1[0]), PIX_CLR);
- }
- Speed = 3 + min(level/3, 3);
- #ifdef DEBUG
- if (debug)
- printf("Speed = %d\n", Speed);
- #endif DEBUG
- clear_sparks();
- update_score();
- moving = STOP;
- drawing = FALSE;
- if (level > 0) {
- msg("All scores now\n%d times\ntheir original value.", level+1);
- sleep(3);
- remove_msgs(0);
- }
- place_pen(); /* make pen appear */
- }
-
- for (x = 0; x < 2; x++)
- for (n = m; n >= 40 && n <= 300; n -= 5 * live_or_die)
- box(pen_coord_x(pen_x)-n/2, pen_coord_y(pen_y)-n/2,
- pen_coord_x(pen_x)+n/2, pen_coord_y(pen_y)+n/2, XOR);
-
- if (live_or_die == DIE) {
- is_alive = FALSE;
- if (--lives <= 0) {
- reset_joystick_win(TRUE);
- msg("Game Over.");
- sleep(2);
- /* if he got on the scoreboard, let him put his initials up */
- if (play_mode == REAL_PLAY)
- score_board(FALSE, FALSE);
- if (play_mode == SHOW_SPIRAL)
- time_left = 50; /* demo mode comes after spiral death trap */
- else {
- score_board(TRUE, FALSE);
- play_mode = SHOW_SCORES;
- time_left = 100; /* show scores after demo mode or real play */
- }
- moving = NO_MOVE;
- } else {
- moving = STOP;
- drawing = 0;
- }
- place_pen(); /* erase pen */
- } else {
- is_alive = TRUE;
- reset_joystick_win(FALSE);
- }
- start_timer();
- }
-
- update_score()
- {
- char buf[128];
- int x;
-
- sprintf(buf, "Score: %6d", score);
- pw_text(joystick_win, 500, 22, PIX_SRC, big_font, buf);
- pw_text(joystick_win, 500, 22, PIX_SRC|PIX_DST, big_font, buf);
-
- if (play_mode != REAL_PLAY) {
- pw_text(draw_win, 105, 12, PIX_SRC, small_font,
- "Click RIGHT mouse button or use <spacebar> to start new game.");
- return;
- }
-
- pw_text(joystick_win, 500, 45, PIX_SRC, big_font, "Lives: ");
- for (x = 0; x < MAX_LIVES; x++)
- pw_rop(joystick_win, 575+(x*20), 32, 16,16, (x < lives-1)?
- PIX_SRC:PIX_CLR, &pen_image, 0, 0);
- sprintf(buf, "Filled: %d%%",(int)((double)area_closed/TOTAL_AREA*100));
- pw_text(draw_win, 280, 12, PIX_SRC, small_font, buf);
- pw_text(draw_win, 281, 12, PIX_SRC|PIX_DST, small_font, buf);
- }
-
- Pixrect *save[15]; /* area under text to be redisplayed upon removal of text */
- int x_save[15], y_save, x_pos[15], y_pos[15];
- static int msgs; /* the number of text lines displayed on the board */
-
- /* print a message somewhere at the top of the playing board for two seconds */
- msg(fmt, args)
- char *fmt;
- {
- char buf[BUFSIZ], *index();
- register char *p2, *p = buf;
-
- y_save = l_height(big_font) + 1;
-
- vsprintf(buf, fmt, &args);
- #ifdef DEBUG
- puts(buf);
- #endif DEBUG
- do {
- if (p2 = index(p, '\n'))
- *p2 = 0;
- x_save[msgs] = strlen(p) * l_width(big_font) + 1;
- x_pos[msgs] = BOARD_WIDTH_IN_PIXELS/2 - x_save[msgs]/2;
- y_pos[msgs] = TOP_BORDER + (1+msgs) * 2 * y_save;
-
- if (!(save[msgs] = mem_create(x_save[msgs], y_save, 1))) {
- puts("whoops! Out of memory... no sense going on with this.");
- exit(1);
- }
- pr_rop(save[msgs], 0, 0, x_save[msgs], y_save, PIX_SRC,
- draw_win->pw_prretained, x_pos[msgs], y_pos[msgs]);
-
- pw_text(draw_win, x_pos[msgs], y_pos[msgs]+l_height(big_font)-5,
- PIX_SRC, big_font, p);
- pw_text(draw_win, x_pos[msgs]+1, y_pos[msgs]+l_height(big_font)-5,
- PIX_SRC|PIX_DST, big_font, p);
- } while (++msgs < 15 && p2 && *(p = p2+1));
- }
-
- /* remove all messages from the board and put back the images underneith */
- remove_msgs(clearing)
- {
- while (msgs--) {
- if (!clearing)
- pw_rop(draw_win, x_pos[msgs], y_pos[msgs], x_save[msgs], y_save,
- PIX_SRC, save[msgs], 0, 0);
- pr_destroy(save[msgs]);
- }
- msgs = 0;
- }
-
- catch(sig)
- {
- stop_timer();
- if (sig == SIGXCPU) {
- msg("CPU timelimit exceeded. Go home and eat dinner.");
- sleep(2);
- remove_msgs(0);
- return;
- }
- change_life(DIE);
- if (sig == SIGSEGV)
- fprintf(stderr, "Segmentation fault.\n");
- else
- fprintf(stderr, "Bus Error\n");
- abort();
- }
-